package com.ziiwee.reduce.commons.utils;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;

public class ListUtil {

    public static <T> boolean anyMatch(List<T> list, Function<T, Boolean> renderMatch) {
        return list.stream().anyMatch(renderMatch::apply);
    }

    public static <T> boolean allMatch(List<T> list, Function<T, Boolean> renderMatch) {
        return list.stream().allMatch(renderMatch::apply);
    }

    /**
     * 分割 list ,通过指定一个对象中的字段为 key
     *
     * @param list
     * @param renderKey
     * @param <K>
     * @param <T>
     * @return
     */
    public static <K, T> Map<K, List<T>> split(List<T> list, Function<T, K> renderKey) {
        Map<K, List<T>> map = new HashMap<>();
        for (T t : list) {
            K key = renderKey.apply(t);
            List<T> value = map.get(key);
            value = value != null ? value : new ArrayList<>();
            value.add(t);
            map.put(key, value);
        }
        return map;
    }

    /**
     * 将 list 中的元素映射成 map
     *
     * @param list
     * @param renderKey
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> Map<K, T> mapping(List<T> list, Function<T, K> renderKey) {
        return mapping(list, renderKey, it -> it);
    }

    public static <T, K, V> Map<K, V> mapping(List<T> list, Function<T, K> renderKey, Function<T, V> renderValue) {
        Map<K, V> map = new HashMap<>();
        for (T t : list) {
            map.put(renderKey.apply(t), renderValue.apply(t));
        }
        return map;
    }

    /**
     * 合并对象中的子 list
     *
     * @param list
     * @param renderChildren
     * @param <T>
     * @return
     */
    public static <T> List<T> mergeChildren(List<T> list, Function<T, List<T>> renderChildren) {
        List<T> result = new ArrayList<>(list);
        for (T t : list) {
            result.addAll(mergeChildren(renderChildren.apply(t), renderChildren));
        }
        return result;
    }

    public static String asString(List<String> list) {
        return asString(list, it -> it);
    }

    public static <T> String asString(Collection<T> list, Function<T, String> handler) {
        return asString(list, (it, i) -> handler.apply(it));
    }

    public static <T> String asString(Collection<T> list, BiFunction<T, Integer, String> handler) {
        StringBuilder sb = new StringBuilder();
        int i = 0;
        for (T t : list) {
            if (handler != null) {
                sb.append(handler.apply(t, i)).append(",");
            } else {
                sb.append(t).append(",");
            }
            i++;
        }
        String val = sb.toString();
        if (val.length() > 0) {
            val = val.substring(0, val.length() - 1);
        }
        return val;
    }

}
